﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


/*
 * 脚本功能：网络消息封装解析类
 * 编写日期：2018.12.13
 * 编写人：HYZ
 */
namespace CFrame.Common
{
    public class Message
    {
        /// <summary>
        /// 保存消息的byte数组
        /// </summary>
        private byte[] data = new byte[1024];
        /// <summary>
        /// 当前数组的存储位置索引
        /// </summary>
        private int startIndex = 0;

        /// <summary>
        /// 保存消息的byte数组
        /// </summary>
        public byte[] Data
        {
            get
            {
                return data;
            }
        }

        /// <summary>
        /// 当前数组的存储位置索引
        /// </summary>
        public int StartIndex
        {
            get
            {
                return startIndex;
            }
        }

        /// <summary>
        /// 当前剩余数据可存储量
        /// </summary>
        public int RemainSize
        {
            get
            {
                return data.Length - startIndex;
            }
        }

        /// <summary>
        /// 读取网络数据
        /// </summary>
        /// <param name="newDataAmount">数据总长度</param>
        /// <param name="Callback">消息获取到的回调方法</param>
        public void ReadMessage(int newDataAmount,Action<int,string> Callback)
        {
            startIndex += newDataAmount;
            while (true)
            {
                if(startIndex <= 4)
                {
                    //说明消息不完成，或者只有包头数据没有消息
                    return;
                }
                //消息结构：{文件大小，类型，消息体}
                //获取前4个字节当前信息的长度，头4个字节存储的是数据的大小
                int count = BitConverter.ToInt32(data, 0);
                //如果减去包头文件的大小比信息的数据量大的话，说明这条数据是完整的，可以执行读取操作
                if((startIndex - 4) >= count)
                {
                    //获取类型
                    int code = BitConverter.ToInt32(data, 4);
                    //获取消息
                    string value = Encoding.UTF8.GetString(data, 8, count - 4);
                    //消息返回
                    Callback(code, value);
                    //后面的数据往前移
                    Array.Copy(data, count + 4, data, 0, startIndex - 4 - count);
                    //更新索引
                    startIndex -= (count + 4);
                }
                else
                {
                    //数据不完整不执行读取操作
                    break;
                }
            }
        }

        /// <summary>
        /// 消息封装
        /// </summary>
        /// <param name="requestCode">对应后端模块</param>
        /// <param name="actionCode">后端模块中的方法</param>
        /// <param name="data">数据</param>
        /// <returns></returns>
        public static byte[] PackData(int requestCode,int actionCode,string data)
        {
            //后台接受数据消息结构:{消息总长度，requestcode,actioncode,data}
            byte[] reqBytes = BitConverter.GetBytes(requestCode);
            byte[] actBytes = BitConverter.GetBytes(actionCode);
            byte[] dataBytes = Encoding.UTF8.GetBytes(data);
            //获取数据总长度
            int dataAmount = reqBytes.Length + actBytes.Length + dataBytes.Length;
            byte[] dataAmountBytes = BitConverter.GetBytes(dataAmount);

            return dataAmountBytes.Concat(reqBytes).ToArray<byte>().Concat(actBytes).ToArray<byte>().Concat(dataBytes).ToArray<byte>();
        }
    }
}
